/**
  ******************************************************************************
  * @file    tc32l010_gpio.c
  * @author  CHIPAT Application Team
  * @brief   This file provides firmware functions to manage the following
  *          functionalities of the GPIO peripheral:
  *           + Initialization and Configuration functions
  *           + GPIO Read and Write functions
  *           + GPIO Alternate functions configuration functions
  *
  @verbatim
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "tc32l010_gpio.h"

#define GPIO_NUMBER           8U


/**
  * @brief  Deinitializes the GPIOx peripheral registers to their default reset
  *         values.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @retval None
  */
void GPIO_DeInit(GPIO_TypeDef* GPIOx)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

    if(GPIOx == GPIOA)
    {
        RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOA, ENABLE);
        RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOA, DISABLE);
    }
    else if(GPIOx == GPIOB)
    {
        RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOB, ENABLE);
        RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOB, DISABLE);
    }
    else if(GPIOx == GPIOC)
    {
        RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOC, ENABLE);
        RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOC, DISABLE);
    }
    else
    {
        if(GPIOx == GPIOD)
        {
            RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOD, ENABLE);
            RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOD, DISABLE);
        }
    }
}

/**
  * @brief  Initializes the GPIOx peripheral according to the specified
  *         parameters in the GPIO_InitStruct.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that contains
  *         the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
    uint32_t pinpos = 0x00, pos = 0x00, currentpin = 0x00;
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
    assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
    assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));

    /*-------------------------- Configure the port pins -----------------------*/
    /*-- GPIO Mode Configuration --*/
    for (pinpos = 0x00; pinpos < GPIO_NUMBER; pinpos++)
    {
        pos = ((uint32_t)0x01) << pinpos;

        /* Get the port pins position */
        currentpin = GPIO_InitStruct->GPIO_Pin & pos;

        if (currentpin == pos)
        {
            /*------------------------- EXTI Mode Configuration --------------------*/
            /* disable interrupt */
            GPIOx->INTEN &= ~(GPIO_INTEN_PxIEN0 << pinpos);

            GPIOx->INTTYPECR &= ~(GPIO_INTTYPCR_PxITYPE0 << pinpos);

            GPIOx->INTPOLCR &= ~(GPIO_INTPOLCR_PxIVAL0 << pinpos);

            GPIOx->INTANY &= ~(GPIO_INTANY_PxIANY0 << pinpos);

            /*------------------------- GPIO Mode Configuration --------------------*/
            /* Configure the default Alternate Function in current IO --GPIO */
            GPIOx->AFR &= ~(GPIO_AFR_PxAFR0 << (pinpos * 4U));

            /* Configure the default value for inout mode --input */
            GPIOx->DIRCR &= ~(GPIO_DIRCR_PxDIRCR0 << pinpos);

            /* Deactivate the Pull-up and Pull-down resistor for the current IO --nopupd*/
            GPIOx->PUPDR &= ~(GPIO_PUPDR_PxPUPD0 << (pinpos * 2U));

            if(GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF)
            {
                /* Configure Alternate function mapped with the current IO */
                GPIOx->AFR &= ~(0xFU << (pinpos * 4U)) ;
                GPIOx->AFR |= ((uint32_t)(GPIO_InitStruct->Alternate) << (pinpos * 4U));
            }
            /* In case of Analog function mode selection */
            else if(GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AN)
            {
                /* Configure Analog function mapped with the current IO */
                GPIOx->AFR &= ~(0xFU << (pinpos * 4U));
                GPIOx->AFR |= ((uint32_t)(0x0FU) << (pinpos * 4U));
            }
            /* In case of Input function mode selection */
            else if(GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IN)
            {
                /* Configure Input function IO */
                GPIOx->DIRCR &= ~(0x01U << pinpos) ;
            }
            /* In case of Output or Alternate function mode selection */
            else if(GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT)
            {
                /* Configure Output function IO */
                GPIOx->DIRCR |= ((uint32_t)(0x01U) << pinpos);
            }

            /* Pull-up Pull down resistor configuration */
            GPIOx->PUPDR &= ~(GPIO_PUPDR_PxPUPD0 << ((uint16_t)pinpos * 2));
            GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));

            /* Set the driver strength for the current IO */
            GPIOx->DRVCR &= ~(GPIO_DRVCR_PxDRV0 << (pinpos * 2U));
            GPIOx->DRVCR |= ((GPIO_InitStruct->GPIO_Drive) << (pinpos * 2U));

        }
    }
}

/**
  * @brief  Fills each GPIO_InitStruct member with its default value.
  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure which will
  *         be initialized.
  * @retval None
  */
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
{
    /* Reset GPIO init structure parameters values */
    GPIO_InitStruct->GPIO_Pin  = GPIO_Pin_All;
    GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStruct->GPIO_Drive = GPIO_Drive_3;
    GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL;
}


/**
  * @}
  */

/**
  * @brief  Reads the specified input port pin.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIO_Pin: specifies the port bit to read.
  * @note   This parameter can be GPIO_Pin_x where x can be:
  *         For XS32L1010: (1..3) for GPIOA, (4,5) for GPIOB, (3..7) for GPIOC and (1, 2..6) for GPIOD.
  * @retval The input port pin value.
  */
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    uint8_t bitstatus = 0x00;

    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

    if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
    {
        bitstatus = (uint8_t)Bit_SET;
    }
    else
    {
        bitstatus = (uint8_t)Bit_RESET;
    }
    return bitstatus;
}

/**
  * @brief  Reads the specified input port pin.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @retval The input port pin value.
  */
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

    return ((uint16_t)GPIOx->IDR);
}

/**
  * @brief  Reads the specified output data port bit.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIO_Pin: Specifies the port bit to read.
  * @note   This parameter can be GPIO_Pin_x where x can be:
  *         For XS32L1010: (1..3) for GPIOA, (4,5) for GPIOB, (3..7) for GPIOC and (1, 2..6) for GPIOD.
  * @retval The output port pin value.
  */
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    uint8_t bitstatus = 0x00;

    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

    if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET)
    {
        bitstatus = (uint8_t)Bit_SET;
    }
    else
    {
        bitstatus = (uint8_t)Bit_RESET;
    }
    return bitstatus;
}

/**
  * @brief  Reads the specified GPIO output data port.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @retval GPIO output data port value.
  */
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

    return ((uint16_t)GPIOx->ODR);
}

/**
  * @brief  Sets the selected data port bits.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIO_Pin: specifies the port bits to be written.
  * @note   This parameter can be GPIO_Pin_x where x can be:
  *         For XS32L1010: (1..3) for GPIOA, (4,5) for GPIOB, (3..7) for GPIOC and (1, 2..6) for GPIOD.
  * @retval None
  */
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GPIO_PIN(GPIO_Pin));

    GPIOx->ODSET = GPIO_Pin;
}

/**
  * @brief  Clears the selected data port bits.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIO_Pin: specifies the port bits to be written.
  * @note   This parameter can be GPIO_Pin_x where x can be:
  *         For XS32L1010: (1..3) for GPIOA, (4,5) for GPIOB, (3..7) for GPIOC and (1, 2..6) for GPIOD.
  * @retval None
  */
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GPIO_PIN(GPIO_Pin));

    GPIOx->ODCLR = GPIO_Pin;
}

/**
  * @brief  Sets or clears the selected data port bit.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIO_Pin: specifies the port bit to be written.
  * @param  BitVal: specifies the value to be written to the selected bit.
  *          This parameter can be one of the BitAction enumeration values:
  *            @arg Bit_RESET: to clear the port pin
  *            @arg Bit_SET: to set the port pin
  * @note   This parameter can be GPIO_Pin_x where x can be:
  *         For XS32L1010: (1..3) for GPIOA, (4,5) for GPIOB, (3..7) for GPIOC and (1, 2..6) for GPIOD.
  * @retval None
  */
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
    assert_param(IS_GPIO_BIT_ACTION(BitVal));

    if (BitVal != Bit_RESET)
    {
        GPIOx->ODSET = GPIO_Pin;
    }
    else
    {
        GPIOx->ODCLR = GPIO_Pin ;
    }
}

/**
  * @brief  Writes data to the specified GPIO data port.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  PortVal: specifies the value to be written to the port output data register.
  * @retval None
  */
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

    GPIOx->ODR = PortVal;
}

/**
  * @brief  Toggles the specified GPIO pins..
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIO_Pin: Specifies the pins to be toggled.
  * @retval None
  */
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

    GPIOx->ODR ^= GPIO_Pin;
}


/**
  * @brief  config the interrupt for specified GPIO pins..
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIOInt_InitTypeDef: pointer to a GPIOInt_InitTypeDef structure
  *         that contains the configuration information for the gpio peripheral.
  * @retval None
  */
void GPIO_INTConfig(GPIO_TypeDef* GPIOx, GPIOInt_InitTypeDef* INT_InitStruct)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_INT_TRIGGER(INT_InitStruct->INT_Trigger));
    assert_param(IS_INT_LINE(INT_InitStruct->INT_Line));
    assert_param(IS_FUNCTIONAL_STATE(INT_InitStruct->INT_LineCmd));

    if (INT_InitStruct->INT_LineCmd != DISABLE)
    {
        /* Select the trigger for the edge interrupts */
        if (INT_InitStruct->INT_Trigger < INT_Trigger_High)
        {
            GPIOx->INTTYPECR &= ~INT_InitStruct->INT_Line;

            if(INT_InitStruct->INT_Trigger == INT_Trigger_Rising_Falling)
            {
                GPIOx->INTANY |= INT_InitStruct->INT_Line;
            }
            else
            {
                GPIOx->INTANY &= ~INT_InitStruct->INT_Line;

                if(INT_InitStruct->INT_Trigger == INT_Trigger_Rising)
                {
                    GPIOx->INTPOLCR |= INT_InitStruct->INT_Line;
                }
                else if(INT_InitStruct->INT_Trigger == INT_Trigger_Falling)
                {
                    GPIOx->INTPOLCR &= ~INT_InitStruct->INT_Line;
                }
            }
        }
        else
        {
            GPIOx->INTTYPECR |= INT_InitStruct->INT_Line;

            if(INT_InitStruct->INT_Trigger == INT_Trigger_High)
            {
                GPIOx->INTPOLCR |= INT_InitStruct->INT_Line;
            }
            else
            {
                GPIOx->INTPOLCR &= ~INT_InitStruct->INT_Line;
            }
        }

        /* Enable the selected gpio lines */
        GPIOx->INTEN |= INT_InitStruct->INT_Line;
    }
    else
    {
        /* Disable the selected gpio lines */
        GPIOx->INTEN &= ~INT_InitStruct->INT_Line;
    }
}


/**
  * @brief  Checks whether the specified GPIO line is asserted or not.
  * @param  INT_Line: specifies the INT line to check.
  *          This parameter can be INT_Line where x can be(0..7)
  * @retval The new state of INT_Line (SET or RESET).
  */
ITStatus GPIO_GetITStatus(GPIO_TypeDef* GPIOx, uint32_t INT_Line)
{
    FlagStatus bitstatus = RESET;

    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GET_INT_LINE(INT_Line));

    if ((GPIOx->MSKINTSR & INT_Line) != (uint32_t)RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;

}

/**
  * @brief  Clears the GPIO's line pending bits.
  * @param  INT_Line: specifies the GPIO lines to clear.
  *          This parameter can be any combination of INT_Line where x can be (0..7)
  * @retval None
  */
void GPIO_ClearITPendingBit(GPIO_TypeDef* GPIOx, uint32_t INT_Line)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_INT_LINE(INT_Line));

    GPIOx->INTCLR = INT_Line;
}


/**
  * @brief  Enables or disables the GPIO's line interrupt bits.
  * @param  GPIOx: where x can be (A, B, C or D) to select the GPIO peripheral.
  * @param  GPIOInt_InitTypeDef: pointer to a GPIOInt_InitTypeDef structure
  *         that contains the configuration information for the gpio peripheral.
  * @param  NewState: new state of the DMA Request sources.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void GPIO_INTCmd(GPIO_TypeDef* GPIOx, uint32_t INT_Line, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_INT_LINE(INT_Line));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected gpio lines */
        GPIOx->INTEN |= INT_Line;
    }
    else
    {
        /* Disable the selected gpio lines */
        GPIOx->INTEN &= ~INT_Line;
    }
}

/**
  * @}
  */


/**
  * @}
  */

/************************ (C) COPYRIGHT CHIPAT *****END OF FILE****/
